package org.budo.support.lang.util;

import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.util.Assert;

/**
 * @author li
 * @version 1 (2016年11月15日 下午10:34:51)
 * @since Java7
 */
public class StringUtil {
    private static final Logger log = Slf4j.getLogger();

    public static String cutRight(String string, int width) {
        if (length(string) <= width) {
            return string;
        }

        int length = string.length();
        return string.substring(length - width);
    }

    public static String cutLeft(String string, int width) {
        if (length(string) <= width) {
            return string;
        }

        return string.substring(0, width);
    }

    public static String cutLeft(String string, int width, String suffix) {
        if (length(string) <= width) {
            return string;
        }

        return string.substring(0, width) + suffix;
    }

    /**
     * 保证字符串为一固定长度。超过长度，切除右侧字符，否则右侧填补字符。
     * 
     * @param string 字符串
     * @param width  长度
     * @param c      补字符
     * @return 修饰后的字符串
     */
    public static String cutLeft(String string, int width, char c) {
        if (null == string) {
            return null;
        }

        int len = string.length();
        if (len == width) {
            return string;
        }

        if (len < width) {
            return string + dup(c + "", width - len);
        }

        return string.substring(0, width);
    }

    public static boolean isAllEmpty(Object[] stringArray) {
        if (stringArray == null || stringArray.length == 0) {
            return true;
        }

        for (Object str : stringArray) {
            if (!StringUtil.isBlank(toString(str))) {
                return false;
            }
        }

        return true;
    }

    public static Boolean equals(String str1, String str2) {
        return (null == str1 && null == str2) || (null != str1 && str1.equals(str2));
    }

    public static Boolean equals(Object str1, Object str2) {
        return (null != str1 && null != str2) && equals(toString(str1), toString(str2));
    }

    public static Integer length(String value) {
        return null == value ? 0 : value.length();
    }

    /**
     * 复制字符串
     * 
     * @param cs  字符串
     * @param num 数量
     * @return 新字符串
     */
    public static String dup(CharSequence charSequence, int num) {
        if (isEmpty(charSequence) || num <= 0) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder(charSequence.length() * num);
        for (int i = 0; i < num; i++) {
            stringBuilder.append(charSequence);
        }
        return stringBuilder.toString();
    }

    public static String[] split(String string, String regex) {
        if (null == string) {
            return new String[0];
        }
        return string.split(regex);
    }

    public static Boolean contains(String str1, String str2) {
        return null != str1 && null != str2 && str1.contains(str2);
    }

    public static boolean equalsIgnoreCase(String str1, String str2) {
        return null != str1 && str1.equalsIgnoreCase(str2);
    }

    /**
     * Checks if a String is whitespace, empty ("") or null.
     */
    public static boolean isBlank(String str) {
        return isEmpty(str) || isEmpty(str.trim());
    }

    /**
     * Checks if a String is empty ("") or null.
     */
    public static boolean isEmpty(CharSequence charSequence) {
        return null == charSequence || charSequence.length() < 1;
    }

    public static Boolean endsWithIgnoreCase(String str1, String str2) {
        return null != str1 && null != str2 && str1.toUpperCase().endsWith(str2.toUpperCase());
    }

    public static Boolean endsWith(String str1, String str2) {
        return null != str1 && null != str2 && str1.endsWith(str2);
    }

    public static Boolean startsWith(String string, String prefix) {
        return null != string && null != prefix && string.startsWith(prefix);
    }

    public static Boolean containsIgnoreCase(String str1, String str2) {
        return null != str1 && null != str2 && str1.toLowerCase().contains(str2.toLowerCase());
    }

    public static String changeCharset(String line, String charsetFrom, String charsetTo) {
        try {
            if (null == line || null == charsetTo) {
                return line;
            } else if (null == charsetFrom) {
                return new String(line.getBytes(), charsetTo);
            } else {
                return new String(line.getBytes(charsetFrom), charsetTo);
            }
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 传入参数是 Serializable[] 数组时,会被判断为二维数组
     */
    public static String join(Object[] array, String linker, String left, String right) {
        if (null == array) {
            return null;
        }

        if (array.length > 0 && null != array[0] && array[0].getClass().isArray()) {
            array = (Object[]) array[0]; // 传入参数是 Serializable[] 数组时,会被判断为二维数组
            log.error("#163 join 传入二维数组, array=" + array + ", linker=" + linker + ", left=" + left + ", right=" + right);
        }

        StringBuffer stringBuffer = new StringBuffer();
        boolean first = true;
        for (Object each : array) {
            if (!first) {
                stringBuffer.append(linker);
            }

            stringBuffer.append(left);
            stringBuffer.append(each);
            stringBuffer.append(right);
            first = false;
        }
        return stringBuffer.toString();
    }

    public static String join(char[] charArray, String linker) {
        Object[] objectArray = ArrayUtil.toObjectArray(charArray);
        return join(objectArray, linker);
    }

    public static String join(Object[] array, String linker) {
        return join(array, linker, "", "");
    }

    public static String join(Object[] array) {
        return join(array, ",", "", "");
    }

    @SuppressWarnings("rawtypes")
    public static String join(Collection collection) {
        return join(collection, ",");
    }

    public static String join(List list) {
        if (null == list) {
            return null;
        }

        return join(list.toArray(), ",");
    }

    public static String _join(Object in) {
        if (null == in) {
            return "null";
        }

        if (in instanceof List) {
            return join((List) in);
        }

        if (in.getClass().isArray()) {
            return join((Object[]) in);
        }

        throw new RuntimeException("#220 in=" + in);
    }

    public static Boolean hasEmpty(String[] array) {
        if (null == array) {
            throw new RuntimeException("array is null");
        }

        for (String each : array) {
            if (isEmpty(each)) {
                return true;
            }
        }

        return false;
    }

    public static String join(Collection<?> collection, String linker, String left, String right) {
        if (null == collection) {
            return null;
        }
        return join(collection.toArray(), linker, left, right);
    }

    public static String join(Collection<?> collection, String linker) {
        if (null == collection) {
            return null;
        }

        return join(collection.toArray(), linker);
    }

    public static String toString(Object object) {
        return null == object ? null : object.toString();
    }

    public static String toString(Object object, String valueWhenNull) {
        return null == object ? valueWhenNull : object.toString();
    }

    /**
     * 将密码间隔一个替换为*
     */
    public static String password(String password) {
        if (null == password || password.isEmpty()) {
            return password;
        }

        char[] chars = password.toCharArray();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            if (i % 2 == 0) { // 偶数
                stringBuffer.append(chars[i]);
            } else {
                stringBuffer.append('*');
            }
        }
        return stringBuffer.toString();
    }

    public static Boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    public static String removeCDATA(String value) {
        if (StringUtil.isEmpty(value)) {
            return value;
        }
        value = value.trim();
        if (value.startsWith("<![CDATA[") && value.endsWith("]]>")) {
            return value.substring(9, value.length() - 3);
        }
        return null;
    }

    public static Boolean startWith(String string, String prefix) {
        return null != string && null != prefix && string.startsWith(prefix);
    }

    public static String trim(String str) {
        return null == str ? null : str.trim();
    }

    public static Boolean endWith(String string, String str) {
        return null != string && null != str && string.toLowerCase().endsWith(str.toLowerCase());
    }

    public static String toUpperCase(String string) {
        return null == string ? null : string.toUpperCase();
    }

    public static String toLowerCase(String string) {
        return null == string ? null : string.toLowerCase();
    }

    /**
     * @param content
     * @param beginIndex
     * @param endIndex   不是长度,为负数时表示从尾部开始截取
     */
    public static String substring(String content, Integer beginIndex, Integer endIndex) {
        if (null == endIndex) {
            return substring(content, beginIndex);
        }

        if (endIndex < 0) {
            int len = content.length();
            return content.substring(len - beginIndex - (-endIndex), len - beginIndex);
        }

        return content.substring(beginIndex, endIndex);
    }

    public static String substring(String content, Integer beginIndex) {
        if (null == content || null == beginIndex) {
            return content;
        }

        return content.substring(beginIndex);
    }

    public static Boolean startWithIgnoreCase(String string, String prefix) {
        return null != string && null != prefix && string.toUpperCase().startsWith(prefix.toUpperCase());
    }

    public static boolean endWithIgnoreCase(String string, String suffix) {
        return null != string && null != suffix && string.toUpperCase().endsWith(suffix.toUpperCase());
    }

    public static String upperCaseFirst(CharSequence charSequence) {
        if (null == charSequence) {
            return null;
        }

        int len = charSequence.length();
        if (len == 0) {
            return "";
        }

        char c = charSequence.charAt(0);
        if (Character.isUpperCase(c)) {
            return charSequence.toString();
        }

        return new StringBuilder(len).append(Character.toUpperCase(c)).append(charSequence.subSequence(1, len)).toString();
    }

    public static String substring(String src, String start, String to) {
        int indexFrom = start == null ? 0 : src.indexOf(start);
        int indexTo = to == null ? src.length() : src.indexOf(to);
        if (indexFrom < 0 || indexTo < 0 || indexFrom > indexTo) {
            return null;
        }

        if (null != start) {
            indexFrom += start.length();
        }

        return src.substring(indexFrom, indexTo);

    }

    public static String substring(String src, String start, String to, boolean toLast) {
        if (!toLast) {
            return substring(src, start, to);
        }
        int indexFrom = start == null ? 0 : src.indexOf(start);
        int indexTo = to == null ? src.length() : src.lastIndexOf(to);
        if (indexFrom < 0 || indexTo < 0 || indexFrom > indexTo) {
            return null;
        }

        if (null != start) {
            indexFrom += start.length();
        }

        return src.substring(indexFrom, indexTo);
    }

    /**
     * 拼接字符串
     */
    public static String contact(String... strs) {
        if (strs == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for (String str : strs) {
            sb.append(str);
        }

        return sb.toString();
    }

    public static String concat_ws(String separator, String... strs) {
        Assert.hasLength(separator, "separator must not be null");
        Assert.notNull(strs, "strs must not be null");
        if (strs.length <= 1) {
            throw new IllegalArgumentException("strs's length must large than 1");
        }

        String[] s = new String[strs.length * 2 - 1];
        for (int i = 1; i <= s.length; i++) {
            if (i % 2 == 1) {
                s[i - 1] = strs[(i + 1) / 2 - 1];
            } else {
                s[i - 1] = separator;
            }
        }

        return contact(s);
    }

    /**
     * 首字母转大写
     */
    public static String firstCharUpper(String data) {
        Assert.hasLength(data, "data must not be null");
        return contact(data.substring(0, 1).toUpperCase(), data.substring(1));
    }

    /**
     * 首字母转小写
     */
    public static String firstCharLower(String data) {
        Assert.hasLength(data, "data must not be null");
        return contact(data.substring(0, 1).toLowerCase(), data.substring(1));
    }

    /**
     * 转为驼峰格式
     */
    public static String converseToHump(String field) {
        Assert.hasLength(field, "field must not be null");
        String _target = field;
        int _j = _target.length();
        for (int _i = 0; _i < _j; _i++) {
            byte ascii = (byte) _target.charAt(_i);
            if (ascii >= 65 && ascii <= 90) {
                if (_i == 0) {
                    _target = firstCharLower(_target);
                } else {
                    byte preAscii = (byte) _target.charAt(_i - 1);
                    if (preAscii == 95) {
                        _target = contact(_target.substring(0, _i), firstCharLower(_target.substring(_i)));
                    } else {
                        _target = contact(_target.substring(0, _i), "_", firstCharLower(_target.substring(_i)));
                        _j++;
                        _i++;
                    }
                }
            }
        }

        return _target;
    }

    /**
     * 驼峰转正常格式
     */
    public static String converseToNormal(String field) {
        Assert.hasLength(field, "field must not be null");
        String _target = field;

        while (_target.startsWith("_")) {
            _target = _target.substring(1, _target.length());
        }

        while (_target.endsWith("_")) {
            _target = _target.substring(0, _target.length() - 1);
        }

        while (_target.contains("_")) {
            _target = _target.substring(0, _target.indexOf("_")) + firstCharUpper(_target.substring(_target.indexOf("_") + 1));
        }

        return _target;
    }

    /**
     * 字符串反转
     */
    public static String reverse(String text) {
        if (isBlank(text)) {
            return null;
        }

        return new StringBuilder(text).reverse().toString();
    }

    /**
     * 判断字符串是否为乱码
     */

    public static boolean isMessyCode(String strName) {
        try {
            Pattern pattern = Pattern.compile("\\s*|\t*|\r*|\n*");
            Matcher matcher = pattern.matcher(strName);
            String after = matcher.replaceAll("");
            String temp = after.replaceAll("\\p{P}", "");
            char[] ch = temp.trim().toCharArray();

            int length = (ch != null) ? ch.length : 0;
            for (int i = 0; i < length; i++) {
                char c = ch[i];
                if (!Character.isLetterOrDigit(c)) {
                    String str = "" + ch[i];
                    if (!str.matches("[\u4e00-\u9fa5]+")) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {

        }

        return false;
    }

    /**
     * 构建get方法
     */
    public static String buildGet(String fieldName) {
        Assert.hasLength(fieldName, "fieldName must not be null");
        return contact("get", firstCharUpper(fieldName));
    }

    /**
     * 构建set方法
     */
    public static String buildSet(String fieldName) {
        Assert.hasLength(fieldName, "fieldName must not be null");
        return contact("set", firstCharUpper(fieldName));
    }

    public static byte[] getUtf8Bytes(String value) {
        if (null == value) {
            return null;
        }

        try {
            return value.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String gb2312_to_iso_8859_1(String value) {
        if (null == value) {
            return value;
        }

        try {
            byte[] bytes = value.getBytes("GB2312");
            return new String(bytes, "ISO_8859_1");
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
